package com.lin.filegraph.utils.componentRule;

import com.lin.filegraph.utils.name.DirSimilarity;
import com.lin.filegraph.utils.threshold.Threshold;
import com.lin.filegraph.utils.compdg.ComponentEdge;
import com.lin.filegraph.utils.compdg.ComponentGraph;
import com.lin.filegraph.utils.compdg.ComponentNode;

import java.util.*;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 16:07
 */

public class Region {

    public static void executeReg(double num, ComponentGraph graph){
        findRegion(num, graph);
//		unionRegion(graph);
    }
    /**
     * 寻找域实体集
     */
    public static void findRegion(double arcSize,ComponentGraph graph){
        for(ComponentNode cn:graph.getAllComponents()){
            cn.setRegion(false);
        }

        int regEdgeNum= Threshold.getRegionEdgeNum(arcSize);//出入边，之和
        int regNum = Threshold.getRegionNum(arcSize);//前K个节点
        System.out.println("域节点："+regNum+"-"+regEdgeNum);

        Map<ComponentNode,Integer> mapRegion = new LinkedHashMap<>();
        for(ComponentNode cn:graph.getAllComponents()){
            int num_pre = graph.getPreComponents(cn).size();
            int num_post = graph.getPostComponents(cn).size();
            /* 域节点标准
             * 1、出入边之和
             * 2、出边不为零
             * 3、规模不超过30%
             */
            if(num_post!=0 &&cn.getAllFiles().size()<=graph.getTotalSize()*Threshold.COMSCALE){//(num_post+num_pre)>regEdgeNum &&
                mapRegion.put(cn, num_post+num_pre);
//				System.out.println(cn.getStrComponentName()+"-"+num_pre+"-"+num_post);
            }
        }
//		System.out.println("————————————————————————————————————————");
        List<Map.Entry<ComponentNode,Integer>> list = new ArrayList<Map.Entry<ComponentNode,Integer>>(mapRegion.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<ComponentNode,Integer>>() {
            @Override
            public int compare(Map.Entry<ComponentNode,Integer> arg0, Map.Entry<ComponentNode,Integer> arg1) {
                return arg1.getValue().compareTo(arg0.getValue());
            }
        });
        int i=0;
        for(Map.Entry<ComponentNode,Integer> cp:list){
            if(i<regNum){
                cp.getKey().setRegion(true);
                System.out.println(cp.getKey().getStrComponentName()+"-"+cp.getValue());
                i++;
            }
            else {
                break;
            }
        }
    }

    /**
     * 域节点聚合
     */
    private static void unionRegion(ComponentGraph graph){
        boolean isfind =false;
        for(ComponentEdge ce:graph.getAllComponentEdges()){
            ComponentNode cn1 = ce.getPreComponent();
            ComponentNode cn2 = ce.getPostComponent();
            if(cn1.isRegion()&&cn2.isRegion()){
                if(getSim(graph, cn1, cn2)){
                    System.out.println("域节点聚合");
                    graph.mergeNodes(cn1, cn2);
//					System.out.println(cn1.getStrComponentName());
                    isfind=true;
                    break;
                }
            }
        }
        if(isfind)
            unionRegion(graph);
    }

    private static boolean getSim(ComponentGraph graph,ComponentNode cn1,ComponentNode cn2){
        double simName = DirSimilarity.getSimLevelOfPath(cn1.getStrComponentName(), cn2.getStrComponentName());
        if(simName>=Threshold.DependSim)
            return true;
//		List<String> com1 =new ArrayList<>();
//		List<String> com2 =new ArrayList<>();
//		int simCom = 0;
//		for(ComponentNode cn:graph.getPreComponents(cn1)){
//			if(cn.equals(cn2))
//				return true;
//			com1.add(cn.getStrComponentName());
//		}
//		for(ComponentNode cn:graph.getPreComponents(cn2)){
//			com2.add(cn.getStrComponentName());
//		}
//
//		for(String s:com1){
//			if(com2.contains(s))
//				simCom++;
//		}
//		if((double)simCom/(com1.size()+com2.size()-simCom)>Threshold.DependSim)
//			return true;
        else
            return false;
    }
}

